package com.ldy.db;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;

import android.R.integer;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import android.widget.AutoCompleteTextView.Validator;

import com.ldy.db.model.Model;
import com.ldy.util.AnnotationUtil;

public class DBManager<T> extends SqliteHelper {

	private Class mClz;

	public DBManager(Context context, Class clz) {
		super(context);
		this.mClz = clz;
	}

	/**
	 * 插入一条数据
	 * 
	 * @param t
	 */
	public void insert(T object) {
		SQLiteDatabase db = null;
		try {
			db = getWritableDatabase();
			ContentValues contentValues = object2ContentValus(object);
			ArrayList<com.ldy.db.model.Model> models = AnnotationUtil.getModel(object.getClass());
			for (Model model : models) {
				if (model.isGeneratedId() || model.isId()) {
					contentValues.remove(model.getColumnName());
				}
			}
			long row = db.insert(AnnotationUtil.getTableName(mClz), null, contentValues);
			if (row > 0) {
				Log.i("data", "insert data success");
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (db != null) {
				db.close();
			}
		}
	}

	/**
	 * 将对象转换为ContentValus
	 * 
	 * @param object
	 * @param contentValues
	 * @param field
	 */
	private ContentValues object2ContentValus(T object) {
		ContentValues contentValues = new ContentValues();
		Class clz = object.getClass();
		Field[] fields = clz.getDeclaredFields();
		for (Field field : fields) {
			com.ldy.annotation.Field f = field.getAnnotation(com.ldy.annotation.Field.class);
			if (f != null) {
				try {
					field.setAccessible(true);
					Object obj = field.get(object);
					if (obj != null) {
						String type = field.getType().toString();
						if (type.endsWith("int") || type.endsWith("Integer")) {
							Integer val = (Integer) obj;
							contentValues.put(AnnotationUtil.getFieldName(field), val);
						}
						if (type.endsWith("String")) {
							contentValues.put(AnnotationUtil.getFieldName(field), obj.toString());
						}
						if (type.endsWith("long") || type.endsWith("Long")) {
							Long val = (Long) obj;
							contentValues.put(AnnotationUtil.getFieldName(field), val);
						}
						if (type.endsWith("Date")) {
							Date date = (Date) obj;
							long time = date.getTime();
							contentValues.put(AnnotationUtil.getFieldName(field), time);
						}
						if (type.endsWith("short") || type.endsWith("Short")) {
							Short val = (Short) obj;
							contentValues.put(AnnotationUtil.getFieldName(field), val);
						}
						if (type.endsWith("double") || type.endsWith("Double")) {
							Double val = (Double) obj;
							contentValues.put(AnnotationUtil.getFieldName(field), val);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}

		return contentValues;
	}

	/**
	 * 查找一个对象
	 * 
	 * @param id
	 * @return
	 */
	public T findById(int id) {
		SQLiteDatabase db = getReadableDatabase();
		Cursor cursor = null;
		T data = null;
		try {
			Class<?> cla = Class.forName(this.mClz.getName());
			data = (T) cla.newInstance();
			cursor = db.query(AnnotationUtil.getTableName(mClz), null, " id = ? ", new String[] { String.valueOf(id) }, null, null, null);
			cursor.moveToFirst(); // 向下走一步，获取一个第一个值
			Field[] fields = this.mClz.getDeclaredFields();
			for (Field field : fields) {
				String fieldName = AnnotationUtil.getFieldName(field);
				if (fieldName != null) {
					setValue(cursor, data, field, fieldName);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (cursor != null) {
				cursor.close();
			}
			if (db != null) {
				db.close();
			}
		}

		return data;
	}

	/**
	 * 通过主键删除一条数据
	 * 
	 * @param id
	 */
	public void deleteById(int id) {
		SQLiteDatabase db = null;
		try {
			db = getWritableDatabase();
			ArrayList<Model> models = AnnotationUtil.getModel(mClz);
			String key = "";
			for (Model model : models) {
				if (model.isGeneratedId() || model.isId()) {
					key = model.getColumnName();
				}
			}
			db.delete(AnnotationUtil.getTableName(mClz), key + " = ? ", new String[] { String.valueOf(id) });
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (db != null) {
				db.close();
			}
		}
	}

	/**
	 * 根据传入的对象的内容，然后修改数据库中的数据 在传入的数据模型中，必须设置主键，是要根据模型中的主键而修改数据库的数据
	 * 
	 * @param object
	 * @return 返回大于0的数值表示更新成功，否则失败
	 */
	public int update(T object) {
		SQLiteDatabase db = getWritableDatabase();
		try {
			ContentValues values = object2ContentValus(object);

			ArrayList<Model> models = AnnotationUtil.getModel(object.getClass());
			String key = "";
			for (Model model : models) {
				if (model.isGeneratedId() || model.isId()) {
					key = model.getColumnName();
				}
			}
			int row = db.update(AnnotationUtil.getTableName(mClz), values, key + " = ? ", new String[] { String.valueOf(values.getAsInteger("id")) });
			return row;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (db != null) {
				db.close();
			}
		}
		return 0;
	}

	/**
	 * 查找全部数据
	 * 
	 * @return
	 */
	public ArrayList<T> findAll() {
		SQLiteDatabase db = getReadableDatabase();
		Cursor cursor = null;
		ArrayList<T> obj = new ArrayList<T>();
		try {
			cursor = db.query(AnnotationUtil.getTableName(mClz), null, null, null, null, null, null);
			while (cursor.moveToNext()) {
				Class<?> clz = Class.forName(mClz.getName());
				T data = (T) clz.newInstance();
				Field[] fields = mClz.getDeclaredFields();
				for (Field field : fields) {
					field.setAccessible(true);
					String fieldName = AnnotationUtil.getFieldName(field);
					setValue(cursor, data, field, fieldName);
				}
				obj.add((T) data);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (cursor != null) {
				cursor.close();
			}
			if (db != null) {
				db.close();
			}
		}

		return obj;
	}

	/**
	 * 将查出的数据，封装为对象
	 * 
	 * @param cursor
	 * @param data
	 * @param field
	 * @param fieldName
	 * @throws IllegalAccessException
	 */
	private void setValue(Cursor cursor, T data, Field field, String fieldName) throws IllegalAccessException {
		if (fieldName != null) {
			field.setAccessible(true);
			String type = field.getType().toString();
			if (type.endsWith("short") || type.endsWith("Short")) {
				field.set(data, cursor.getShort(cursor.getColumnIndexOrThrow(fieldName)));
			}
			if (type.endsWith("int") || type.endsWith("Integer")) {
				field.set(data, cursor.getInt(cursor.getColumnIndexOrThrow(fieldName)));
			}
			if (type.endsWith("long") || type.endsWith("Long")) {
				field.set(data, cursor.getLong(cursor.getColumnIndexOrThrow(fieldName)));
			}
			if (type.endsWith("String")) {
				field.set(data, cursor.getString(cursor.getColumnIndexOrThrow(fieldName)));
			}
			if (type.endsWith("float") || type.endsWith("Float")) {
				field.set(data, cursor.getFloat(cursor.getColumnIndexOrThrow(fieldName)));
			}
			if (type.endsWith("double") || type.endsWith("Double")) {
				field.set(data, cursor.getDouble(cursor.getColumnIndexOrThrow(fieldName)));
			}
			if (type.endsWith("Date")) {
				long time = cursor.getLong(cursor.getColumnIndexOrThrow(fieldName));
				if (time != 0) {
					Date date = new Date(time);
					field.set(data, date);
				} else {
					field.set(data, null);
				}
			}
		}
	}

	/**
	 * 通过sql查询数据
	 * 
	 * @param sql
	 */
	public ArrayList<T> select(String sql, String[] selectionArgs) {
		ArrayList<T> obj = new ArrayList<T>();
		SQLiteDatabase db = getReadableDatabase();
		Cursor cursor = null;
		try {
			cursor = db.rawQuery(sql, selectionArgs); 
			while (cursor.moveToNext()) {
				Class<?> clz = Class.forName(mClz.getName());
				T data = (T) clz.newInstance();
				Field[] fields = mClz.getDeclaredFields();
				for (Field field : fields) {
					field.setAccessible(true);
					String fieldName = AnnotationUtil.getFieldName(field);
					setValue(cursor, data, field, fieldName);
				}
				obj.add((T) data);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if(cursor != null) {
				cursor.close();
			}
			if(db != null) {
				db.close();
			}
		}
		return obj;
	}
	
	/**
	 * 返回一条数据
	 * @param sql 可以使用 QueryBuilder 拼接sql，也可以自己写
	 * @param selectionArgs ，如果是用QueryBuilder拼接，则selectionArgs 为null
	 * @return
	 */
	public T queryForFirst(String sql,String[]selectionArgs ) {
		SQLiteDatabase db = getReadableDatabase();
		Cursor cursor;
		T data = null;
		try {
			Class<?> clz = Class.forName(mClz.getName());
			data = (T) clz.newInstance();
			cursor = db.rawQuery(sql, selectionArgs);
			cursor.moveToNext(); // 指针向下走一步
			
			Field[] fields = mClz.getDeclaredFields();
			for (Field field : fields) {
				field.setAccessible(true);
				String fieldName = AnnotationUtil.getFieldName(field);
				setValue(cursor, data, field, fieldName);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return data;
	}

}
